extends Control
class_name Monster

var data_monster: DataMonster

var press_pos := Vector2.ZERO

var is_selected = false

const dead_ani_time = 1
var dead_ani_time_rest = dead_ani_time

const black_ani_time = 1
var black_ani_time_rest = black_ani_time

var attack_target: Control = null


signal pressed()

signal black_monster_finish(monster_scene: Monster)

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	if data_monster:

		if data_monster.is_elite:
			$Back/Name.text = data_monster.name + "【精英】"
			# 名称调整为绿色
			$Back/Name.add_theme_color_override("font_color",Color.GREEN)
		else:
			$Back/Name.text = data_monster.name
		_update_hp()
		# 监听受伤事件
		data_monster.role_hurted.connect(_on_get_hurted)
		# 监听死亡事件
		data_monster.role_dead.connect(_on_role_dead)
		# 监听特效添加事件
		data_monster.effect_created.connect(_on_effect_created)
		data_monster.effect_added.connect(_on_effect_updated)
		data_monster.effect_reduced.connect(_on_effect_updated)
		data_monster.effect_removed.connect(_on_effect_removed)
		# 监听充能开始
		data_monster.charge_started.connect(_on_charge_started)
		# 监听充能完成
		data_monster.charge_completed.connect(_on_charge_completed)
		# 监听怪物重置事件
		data_monster.monster_reseted.connect(_on_monster_reseted)
		# 监听怪物黑化事件
		data_monster.monster_blacked.connect(_on_monster_blacked)


func _enter_tree() -> void:
	if data_monster:
		# 怪物黑化动画过程中切换地图，重新进入地图后直接触发黑化完成效果
		if data_monster.is_black_monster and data_monster.is_dead:
			_on_monster_black_finish()


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	if data_monster:
		data_monster.process(delta)

		_process_attack(delta)

		if data_monster.is_dead:
			# 更新死亡动画
			if dead_ani_time_rest > 0:
				dead_ani_time_rest -= delta
				# 更新透明度动画
				var alpha = dead_ani_time_rest / dead_ani_time
				modulate.a = alpha
			else:
				# 死亡动画播放完毕，如果怪物是黑化怪物，则播放黑化动画
				if data_monster.is_black_monster:
					black_ani_time_rest -= delta
					if black_ani_time_rest > 0:
						# 更新透明度动画
						var ani_scale = black_ani_time_rest / black_ani_time
						var color_value = 0.3 + ani_scale * 0.7
						modulate = Color(color_value,color_value,color_value,1 - ani_scale)


func clear():
	data_monster.role_hurted.disconnect(_on_get_hurted)
	data_monster.role_dead.disconnect(_on_role_dead)
	data_monster.effect_created.disconnect(_on_effect_created)
	data_monster.effect_added.disconnect(_on_effect_updated)
	data_monster.effect_reduced.disconnect(_on_effect_updated)
	data_monster.effect_removed.disconnect(_on_effect_removed)
	data_monster.charge_started.disconnect(_on_charge_started)
	data_monster.charge_completed.disconnect(_on_charge_completed)
	data_monster.monster_reseted.disconnect(_on_monster_reseted)


func _process_attack(delta: float):
	# 眩晕状态无法移动
	if data_monster and data_monster.is_dizziness():
		return
	if attack_target:
		if attack_target is Player:
			_process_attack_player(attack_target,delta)
		elif attack_target is Monster:
			_process_attack_monster(attack_target,delta)


func _process_attack_monster(_attack_target: Monster,delta: float):
	if _attack_target.data_monster == null or _attack_target.data_monster.is_dead:
		return
	# 如果自身是黑化怪物，且目标是黑化怪物，则清空攻击目标
	if data_monster.is_black_monster and _attack_target.data_monster.is_black_monster:
		set_attack_target(null)
		return

	# 如果目标距离大于技能距离，则移动
	if global_position.distance_to(_attack_target.global_position) > data_monster.skill.distance:
		_move_to_attack_target(delta)
	else:
		data_monster.process_attack()	


func _process_attack_player(_attack_target: Player,delta: float):
	# 攻击玩家的处理逻辑
	var data_player = _attack_target.data_player
	if data_player.is_dead:
		return
	# 普通怪物在目标休息时会丢失目标
	if (data_player.is_resting and data_monster.type == "normal" \
		and not data_monster.auto_lock_player and not data_monster.is_ignore_rest):
		_attack_target = null
		return

	if not data_player.can_not_be_hurt:
		# 如果攻击目标是玩家，且已经离开了当前地图，则不进行攻击
		if data_player.map_id != data_monster.current_map_id:
			set_attack_target(null)
			return
		# 如果目标距离大于技能距离，则移动
		if global_position.distance_to(_attack_target.global_position) > data_monster.skill.distance:
			_move_to_attack_target(delta)
		else:
			data_monster.process_attack()	


func _move_to_attack_target(delta: float):
	if data_monster.is_dead:
		return
	var move_direction = attack_target.global_position - global_position
	move_direction = move_direction.normalized()
	# 速度
	var speed = data_monster.attribute.get_final_details().move_speed * SingletonGame.speed
	position += move_direction * speed * delta


func set_attack_target(target: Control):
	attack_target = target
	data_monster.set_combat(target!=null)


func select():
	if is_selected:
		return
		
	var style_box =  load("res://theme/monster_selected.tres")
	#StyleBoxFlat
	$Back.add_theme_stylebox_override("panel",style_box)
	is_selected = true


func unselect():
	if not is_selected:
		return

	$Back.remove_theme_stylebox_override("panel")
	is_selected = false


func _on_get_hurted(_data_role: DataRole,data_damage: DataDamage):
	_update_hp()

	# 添加受伤晃动效果
	if data_damage.value > 0:
		_shake_effect(data_damage.direction)
		
	_add_damage(data_damage)


func _on_role_dead(data_role: DataRole):
	# 开启释放定时器
	$FreeTimer.start()


func _on_effect_created(_data_effect: DataEffect):
	if data_monster and _data_effect.id == "effect_000023":
		# 撕裂
		$DeepDamageLabel.show()
		$DeepDamageLabel.text = "裂" + str(int(_data_effect.value))
	if data_monster and _data_effect.id == "effect_000029":
		# 越战越勇
		$TimeAddDamageLabel.show()
	# 眩晕状态
	if _data_effect.type == "dizziness":
		$DizzinessLabel.show()


func _on_effect_updated(_data_effect: DataEffect):
	if data_monster and _data_effect.id == "effect_000023":
		$DeepDamageLabel.text = "裂" + str(int(_data_effect.value))


func _on_effect_removed(_data_effect: DataEffect):
	if data_monster and _data_effect.id == "effect_000029":
		# 越战越勇
		$TimeAddDamageLabel.hide()
	# 眩晕状态
	if _data_effect.type == "dizziness":
		$DizzinessLabel.hide()


func _update_hp():
	$Back/HpBar/ColorBar.set_value(data_monster.attribute.final_details.max_hp,data_monster.hp)
	if $Back/HpBar.has_node("HP"):
		$Back/HpBar/HP.text = str(data_monster.hp) + "/" + str(data_monster.attribute.final_details.max_hp)


func _add_damage(damage: DataDamage):
	if SingletonGame.perform_mode:
		return
	var damage_scene = SingletonGameScenePre.DamageTextScene.instantiate()
	damage_scene.set_damage(damage)
	if damage.type == DataDamage.TYPE.POISON or damage.type == DataDamage.TYPE.FIRE:
		$PoisonDamageGroup.add(damage_scene)
	else:
		$DamageGroup.add(damage_scene)


func _on_panel_my_released(_ui: Control) -> void:
	pressed.emit()
	# 测试代码
	#_shake_effect()
	#var skill = DataBaseSkill.new("测试技能","attack")
	#skill.name = "测试技能"
	#add_skill_execute_effect(skill,Vector2.RIGHT)

	
func add_skill_execute_effect(skill: DataBaseSkill,direction: Vector2):
	# 性能模式不展示该信息
	if SingletonGame.perform_mode:
		return
	# 实例化技能名称场景
	var skill_name_scene = SingletonGameScenePre.SkillNameScene.instantiate()
	skill_name_scene.set_skill(skill)
	# 技能名称的跳出方向是目标的方向
	skill_name_scene.direction = -direction
	$SkillNameGroup.add_child(skill_name_scene)


# 新版受伤效果，符合物理击退效果
var current_shake_tween: Tween = null

func _shake_effect(direction: Vector2 = Vector2.RIGHT):
	# BOSS无击退效果
	if data_monster.type == "boss":
		return
	# 如果当前有动画，则跳过
	if current_shake_tween:
		return
	
	# 创建新的Tween动画
	current_shake_tween = create_tween().set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
	
	# 动画作用对象
	var shake_obj = $Back
	# 参数配置
	var push_distance = 10.0    # 击退距离
	var shake_intensity = 3.0   # 晃动强度
	var push_duration = 0.1    # 击退时间
	var shake_duration = 0.1    # 晃动时间
	var return_duration = 0.2  # 回弹时间
	
	# 标准化方向向量
	direction = direction.normalized()
	
	# 初始位置
	var original_pos = shake_obj.position
	
	# 1. 快速击退阶段
	current_shake_tween.tween_property(shake_obj, "position", 
		original_pos + direction * push_distance, 
		push_duration)
	
	# 2. 击退后4次左右晃动效果
	var shake_pos = original_pos + direction * push_distance
	var shake_duration_part = shake_duration / 4
	
	# 第一次向左晃动
	current_shake_tween.tween_property(shake_obj, "position:x", 
		shake_pos.x - shake_intensity, 
		shake_duration_part)
	# 回到中心
	current_shake_tween.tween_property(shake_obj, "position:x", 
		shake_pos.x, 
		shake_duration_part)
	
	#保持Y轴位置不变
	current_shake_tween.parallel().tween_property(shake_obj, "position:y", 
		shake_pos.y, 
		shake_duration)
	
	# 3. 延迟后回弹
	current_shake_tween.tween_property(shake_obj, "position", 
		original_pos, 
		return_duration).set_delay(0.2)

	current_shake_tween.finished.connect(_on_shake_finished)


func _on_shake_finished():
	current_shake_tween = null


func _on_charge_started():
	# 显示充能特效
	$ChargeEffect.show()


func _on_charge_completed(_time: float):
	# 隐藏充能特效
	$ChargeEffect.hide()


func close_monitorable():
	# 关闭碰撞体检测（会穿图）
	$Area2D.monitorable = false


func start_monitorable():
	$Area2D.monitorable = true


func _on_monster_reseted(_data_monster: DataMonster):
	_update_hp()
	# 清除撕裂标识
	$DeepDamageLabel.hide()
	

func _on_monster_blacked(_data_monster: DataMonster):
	# 重置攻击目标
	set_attack_target(null)
	# 停止释放定时器
	$FreeTimer.stop()
	# 2秒后黑化完成，切换属性
	if get_tree() == null:
		return
	await get_tree().create_timer(2.0).timeout
	_on_monster_black_finish()


func _on_monster_black_finish():
	# 调整名称
	$Back/Name.text = data_monster.name + "(黑)"
	# 颜色
	dead_ani_time_rest = 0
	black_ani_time_rest = 0
	var color_value = 0.3
	modulate = Color(color_value,color_value,color_value,1)
	# 黑化完成
	data_monster.set_black_finish()

	black_monster_finish.emit(self)


func _on_free_timer_timeout() -> void:
	clear()
	queue_free()


func _reset_dead_animation():
	dead_ani_time_rest = dead_ani_time
